package com.logistica.metropolitana.db.daos;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.logistica.metropolitana.db.model.Grupo;
import com.logistica.metropolitana.db.model.GrupoPermiso;
import com.logistica.metropolitana.db.model.Permiso;
import com.logistica.metropolitana.db.model.Usuario;
import com.logistica.metropolitana.exceptions.UsuarioException;

@Repository
public class UsuarioDAO extends HibernateDaoSupport{

	private final Logger logger = LoggerFactory.getLogger(UsuarioDAO.class);
	
	@Autowired
	public UsuarioDAO(SessionFactory sessionFactory) {
		setSessionFactory(sessionFactory);
	}
	
	@SuppressWarnings("unchecked")
	public List<Grupo> getListaDeRoles() throws UsuarioException {
		try{
			logger.info("Obteniendo lista de Roles");
			Query query = getSession().getNamedQuery("Grupo.findAll");			
			return query.list();
		}catch(Exception e){
			UsuarioException fException = new UsuarioException(e, 
					UsuarioException.LAYER_DAO, UsuarioException.ACTION_SELECT);
			throw fException;
		}
	}

	@SuppressWarnings("unchecked")
	public List<GrupoPermiso> getRolPermisos() throws UsuarioException {
		try{
			logger.info("Obteniendo lista de Roles y Permisos");
			Query query = getSession().getNamedQuery("GrupoPermiso.findAll");			
			return query.list();
		}catch(Exception e){
			UsuarioException fException = new UsuarioException(e, 
					UsuarioException.LAYER_DAO, UsuarioException.ACTION_SELECT);
			throw fException;
		}
	}

	@SuppressWarnings("unchecked")
	public List<String> getPermisosByUsername(String username) throws UsuarioException {
		try{
			logger.info("Obteniendo Permisos por usuario {}", username);

			StringBuilder sql = new StringBuilder();
			sql.append("SELECT NOMBRE_PERMISO FROM USUARIO u ")
				.append("INNER JOIN PERMISO p ON u.ID_USR = p.ID_USR  ")
			 	.append("WHERE u.USERNAME = :username");
			
			Query query = getSession().createSQLQuery(
					sql.toString()).setParameter("username", username);
					
			return query.list();
		}catch(Exception e){
			UsuarioException fException = new UsuarioException(e, 
					UsuarioException.LAYER_DAO, UsuarioException.ACTION_SELECT);
			throw fException;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Usuario> getListaDeUsuarios() throws UsuarioException {
		try{
			logger.info("Obteniendo lista de Usuarios");
			Query query = getSession().getNamedQuery("Usuario.findAll");			
			return query.list();
		}catch(Exception e){
			UsuarioException fException = new UsuarioException(e, 
					UsuarioException.LAYER_DAO, UsuarioException.ACTION_SELECT);
			throw fException;
		}
	}
	
	public Usuario getUsuarioByUsername(String username) throws UsuarioException {
		try{
			Query query = getSession().createQuery("SELECT u FROM Usuario u WHERE u.username = :username")
					.setParameter("username", username);
			
			return (Usuario) query.uniqueResult();
		}catch(Exception e){
			UsuarioException fException = new UsuarioException(e, 
					UsuarioException.LAYER_DAO, UsuarioException.ACTION_SELECT);
			throw fException;
		}
	}

	public void addPermisosPorUsuario(List<Permiso> permisos, int usrId) throws UsuarioException {
		
		Transaction tx = getSession().beginTransaction();
		try{
			
			getSession().createSQLQuery("DELETE FROM PERMISO WHERE ID_USR = :usrId")
					.setParameter("usrId", new Integer(usrId)).executeUpdate();
			
			for (Permiso permiso : permisos) {
				getSession().createSQLQuery("INSERT INTO PERMISO (ID_USR, NOMBRE_PERMISO, FECHA_ALTA_PERMISO) VALUES (:usrId, :nombrePermiso, now())")
				.setParameter("usrId", usrId).setParameter("nombrePermiso", permiso.getNombrePermiso()).executeUpdate();
			}
			
			tx.commit();		
		}catch(Exception e){
			tx.rollback();
			UsuarioException fException = new UsuarioException(e, 
					UsuarioException.LAYER_DAO, UsuarioException.ACTION_UPDATE);
			throw fException;
		}
	}

}
